/**
 * Copyright (c) 2012, Kevin Krile
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, 
 *   this list of conditions and the following disclaimer in the documentation 
 *   and/or other materials provided with the distribution.
 * - Neither the name of the University of Minnesota nor the names of its 
 *   contributors may be used to endorse or promote products derived from this 
 *   software without specific prior written permission.
 *   
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 */

package test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import edu.umn.se.trap.TravelFormMetadata;
import edu.umn.se.trap.TravelFormProcessor;
import edu.umn.se.trap.TravelFormProcessorIntf;
import databases.CurrencyDB;
import databases.GrantDB;
import databases.PerDiemDB;
import databases.UserDB;
import databases.UserGrantDB;
import edu.umn.se.trap.exceptions.FormMemoryException;
import edu.umn.se.trap.exceptions.TrapException;

/**
 * Provides some basic tests for TRAP using the information given in the coding
 * assignment.
 * 
 * This was built using JUnit 4.10 and Hamcrest 1.1.0.
 * 
 * @author Kevin
 */
public class TravelFormProcessorTestSaveForm {
    // --------------------------------------------------------------------------
    // DATA MEMBERS
    // --------------------------------------------------------------------------
    /**
     * The object under test.
     */
    protected TravelFormProcessorIntf testProcessor;

    /**
     * The input form to test
     */
    private Map<String, String> inputFormData = new HashMap<String, String>();

    /**
     * The expected output
     */
    private Map<String, String> outputFormData = new HashMap<String, String>();

    private String description = "";
    
    // The DBs to use to initialize TravelFormProcessor.
    private CurrencyDB currencyDB = new CurrencyDB();
    private GrantDB grantDB = new GrantDB();
    private PerDiemDB perDiemDB = new PerDiemDB();
    private UserDB userDB = new UserDB();
    private UserGrantDB userGrantDB = new UserGrantDB();

    

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    
    // --------------------------------------------------------------------------
    // STATIC INTIALIZERS
    // --------------------------------------------------------------------------
    /**
     * Generates a default, valid, input form.
     * 
     * @return a valid travel input form for use in testing
     */
    public static Map<String, String> getDefaultForm() {
        Map<String, String> formData = new HashMap<String, String>();
        formData.put("USER_NAME", "linc001");
        formData.put("ARRIVAL_DATETIME", "20121112 235900");
        formData.put("DEPARTURE_DATETIME", "20121108 100000");

        formData.put("TRAVEL_TYPE_CSE_SPONSORED", "yes");
        formData.put("EMERGENCY_CONTACT_NAME", "Greg Gay");
        formData.put("EMERGENCY_CONTACT_PHONE", "765-432-1098");
        formData.put("JUSTIFICATION_CONFERENCE_TITLE",
                "ASE2012: 26th IEEE/ACM International Conference on "
                        + "Automated Software Engineering");
        formData.put("JUSTIFICATION_PRESENTED", "no");
        formData.put("JUSTIFICATION_SPONSORED",
                "Learn about research in the field.");
        formData.put("NUM_GRANTS", "1");
        formData.put("GRANT1_ACCOUNT", "010101010101");
        formData.put("GRANT1_PERCENT", "100");
        formData.put("NUM_OTHER_EXPENSES", "2");
        formData.put("OTHER1_DATE", "20121003");
        formData.put("OTHER1_JUSTIFICATION", "Conference Registration");
        formData.put("OTHER1_AMOUNT", "450");
        formData.put("OTHER1_CURRENCY", "USD");
        formData.put("OTHER2_DATE", "20121003");
        formData.put("OTHER2_JUSTIFICATION", "Workshop Registration");
        formData.put("OTHER2_AMOUNT", "100");
        formData.put("OTHER2_CURRENCY", "USD");
        formData.put("NUM_DAYS", "5");
        formData.put("DAY1_LUNCH_CITY", "Des Moines");
        formData.put("DAY1_LUNCH_STATE", "IA");
        formData.put("DAY1_LUNCH_COUNTRY", "USA");
        formData.put("DAY1_DINNER_CITY", "Kansas City");
        formData.put("DAY1_DINNER_STATE", "MO");
        formData.put("DAY1_DINNER_COUNTRY", "USA");
        formData.put("DAY1_LODGING_CITY", "Lawrence");
        formData.put("DAY1_LODGING_STATE", "KS");
        formData.put("DAY1_LODGING_COUNTRY", "USA");
        formData.put("DAY1_LODGING_AMOUNT", "86.31");
        formData.put("DAY1_LODGING_CURRENCY", "USD");
        //new
        formData.put("DAY2_BREAKFAST_CITY", "Lawrence");
        formData.put("DAY2_BREAKFAST_STATE", "KS");
        formData.put("DAY2_BREAKFAST_COUNTRY", "USA");
        //end new
        formData.put("DAY2_LUNCH_CITY", "Lawrence");
        formData.put("DAY2_LUNCH_STATE", "KS");
        formData.put("DAY2_LUNCH_COUNTRY", "USA");
        formData.put("DAY2_DINNER_CITY", "Lawrence");
        formData.put("DAY2_DINNER_STATE", "KS");
        formData.put("DAY2_DINNER_COUNTRY", "USA");
        formData.put("DAY2_LODGING_CITY", "Lawrence");
        formData.put("DAY2_LODGING_STATE", "KS");
        formData.put("DAY2_LODGING_COUNTRY", "USA");
        formData.put("DAY2_LODGING_AMOUNT", "86.31");
        formData.put("DAY2_LODGING_CURRENCY", "USD");
        formData.put("DAY3_BREAKFAST_CITY", "zurich");
        formData.put("DAY3_BREAKFAST_COUNTRY", "switzerland");
        formData.put("DAY3_LODGING_CITY", "Lawrence");
        formData.put("DAY3_LODGING_STATE", "KS");
        formData.put("DAY3_LODGING_COUNTRY", "USA");
        formData.put("DAY3_LODGING_AMOUNT", "86.31");
        formData.put("DAY3_LODGING_CURRENCY", "USD");
        formData.put("DAY4_DINNER_CITY", "Lawrence");
        formData.put("DAY4_DINNER_STATE", "KS");
        formData.put("DAY4_DINNER_COUNTRY", "USA");
        formData.put("DAY4_BREAKFAST_COUNTRY", "switzerland");
/*
        //new stuff
        formData.put("DAY5_BREAKFAST_CITY", "Zurich");
        formData.put("DAY5_BREAKFAST_COUNTRY", "switzerland");
        formData.put("DAY5_LUNCH_CITY", "Zurich");
        formData.put("DAY5_LUNCH_COUNTRY", "switzerland");
        formData.put("DAY5_DINNER_CITY", "Zurich");
        formData.put("DAY5_DINNER_COUNTRY", "switzerland");

        formData.put("DAY6_BREAKFAST_COUNTRY", "switzerland");
        formData.put("DAY6_LUNCH_COUNTRY", "switzerland");
        formData.put("DAY6_DINNER_COUNTRY", "switzerland");
*/
        //end new stuff
        
        formData.put("DAY4_LODGING_CITY", "Lawrence");
        formData.put("DAY4_LODGING_STATE", "KS");
        formData.put("DAY4_LODGING_COUNTRY", "USA");
        formData.put("DAY4_LODGING_AMOUNT", "86.31");
        formData.put("DAY4_LODGING_CURRENCY", "USD");
        //changed day
        formData.put("DAY5_DINNER_CITY", "Des Moines");
        formData.put("DAY5_DINNER_STATE", "IA");
        formData.put("DAY5_DINNER_COUNTRY", "USA");
        //end changed day
        formData.put("NUM_TRANSPORTATION", "6");
        formData.put("TRANSPORTATION1_DATE", "20121108");
        formData.put("TRANSPORTATION1_TYPE", "PARKING");
        formData.put("TRANSPORTATION1_AMOUNT", "12.00");
        formData.put("TRANSPORTATION1_CURRENCY", "USD");
        formData.put("TRANSPORTATION2_DATE", "20121109");
        formData.put("TRANSPORTATION2_TYPE", "PARKING");
        formData.put("TRANSPORTATION2_AMOUNT", "13.00");
        formData.put("TRANSPORTATION2_CURRENCY", "USD");
        formData.put("TRANSPORTATION3_DATE", "20121110");
        formData.put("TRANSPORTATION3_TYPE", "PARKING");
        formData.put("TRANSPORTATION3_AMOUNT", "12.00");
        formData.put("TRANSPORTATION3_CURRENCY", "USD");
        formData.put("TRANSPORTATION4_DATE", "20121110");
        formData.put("TRANSPORTATION4_TYPE", "PARKING");
        formData.put("TRANSPORTATION4_AMOUNT", "22");
        formData.put("TRANSPORTATION4_CURRENCY", "USD");
        formData.put("TRANSPORTATION5_DATE", "20121110");
        formData.put("TRANSPORTATION5_TYPE", "TOLL");
        formData.put("TRANSPORTATION5_AMOUNT", "1.65");
        formData.put("TRANSPORTATION5_CURRENCY", "USD");
        formData.put("TRANSPORTATION6_DATE", "20121110");
        formData.put("TRANSPORTATION6_TYPE", "TOLL");
        formData.put("TRANSPORTATION6_AMOUNT", "1.60");
        formData.put("TRANSPORTATION6_CURRENCY", "USD");

        return formData;
    }

    /**
     * Generates a default, valid, input form.
     * 
     * @return a valid travel input form for use in testing
     */
    public static Map<String, String> getEmptyForm() {
        Map<String, String> formData = new HashMap<String, String>();

        return formData;
    }

    /**
     * Generates a default, valid, input form.
     * 
     * @return a valid travel input form for use in testing
     */
    public static Map<String, String> getIncompleteForm() {
        Map<String, String> formData = new HashMap<String, String>();
        formData.put("USER_NAME", "linc002");

        return formData;
    }

    /**
     * Generates a default, valid, output form without the
     * FORM_SUBMISSION_DATETIME field.
     * 
     * @return a valid travel output form for use in testing
     */
    public static Map<String, String> getOutputForm() {
        Map<String, String> formData = new HashMap<String, String>();

        formData.put("NAME", "Lincoln, Abraham");
        formData.put("USER_NAME", "linc001");
        formData.put("EMAIL", "linc001@umn.edu");
        formData.put("CITIZENSHIP", "United States");

        // We omit this because we have to check it separately.
        // formData.put("FORM_SUBMISSION_DATETIME",
        // "This one depends on the test");
        formData.put("DEPARTURE_DATETIME", "20121108 100000");
        formData.put("ARRIVAL_DATETIME", "20121112 235900");
        formData.put("PAID_BY_UNIVERSITY", "yes");
        formData.put("EMERGENCY_CONTACT_NAME", "Greg Gay");
        formData.put("EMERGENCY_CONTACT_PHONE", "765-432-1098");
        formData.put("TRAVEL_TYPE_CSE_SPONSORED", "yes");
        formData.put("JUSTIFICATION_CONFERENCE_TITLE",
                "ASE2012: 26th IEEE/ACM International Conference on "
                        + "Automated Software Engineering");
        formData.put("JUSTIFICATION_PRESENTED", "no");
        formData.put("JUSTIFICATION_SPONSORED",
                "Learn about research in the field.");
        formData.put("NUM_DESTINATIONS", "5");
        formData.put("DESTINATION1_CITY", "Des Moines");
        formData.put("DESTINATION1_STATE", "IA");
        formData.put("DESTINATION1_COUNTRY", "USA");
        formData.put("DESTINATION2_CITY", "Kansas City");
        formData.put("DESTINATION2_STATE", "MO");
        formData.put("DESTINATION2_COUNTRY", "USA");
        formData.put("DESTINATION3_CITY", "Lawrence");
        formData.put("DESTINATION3_STATE", "KS");
        formData.put("DESTINATION3_COUNTRY", "USA");
        formData.put("DESTINATION4_CITY", "zurich");
        formData.put("DESTINATION4_COUNTRY", "switzerland");
        formData.put("DESTINATION5_CITY", "");
        formData.put("DESTINATION5_COUNTRY", "switzerland");
        formData.put("NUM_DAYS", "5");
        formData.put("DAY1_DATE", "20121108");
        formData.put("DAY1_TOTAL", "111.81");
        formData.put("DAY2_DATE", "20121109");
        formData.put("DAY2_TOTAL", "127.31");
        formData.put("DAY3_DATE", "20121110");
        formData.put("DAY3_TOTAL", "98.31");
        formData.put("DAY4_DATE", "20121111");
        formData.put("DAY4_TOTAL", "119.31");
        formData.put("DAY5_DATE", "20121112");
        //new
 /*       formData.put("DAY5_TOTAL", "109.31");
        formData.put("DAY6_DATE", "20121113");
        formData.put("DAY6_TOTAL", "109.31");
        formData.put("DAY7_DATE", "20121114");
        formData.put("DAY7_TOTAL", "109.31");
        formData.put("DAY8_DATE", "20121115");
        formData.put("DAY8_TOTAL", "0");
        formData.put("DAY9_DATE", "20121116");
*/        formData.put("DAY5_TOTAL", "17.25");
        //end new
        formData.put("NUM_TRANSPORTATION", "6");
        formData.put("TRANSPORTATION1_DATE", "20121108");
        formData.put("TRANSPORTATION1_TYPE", "PARKING");
        formData.put("TRANSPORTATION1_TOTAL", "12.00");
        formData.put("TRANSPORTATION2_DATE", "20121109");
        formData.put("TRANSPORTATION2_TYPE", "PARKING");
        formData.put("TRANSPORTATION2_TOTAL", "13.00");
        formData.put("TRANSPORTATION3_DATE", "20121110");
        formData.put("TRANSPORTATION3_TYPE", "PARKING");
        formData.put("TRANSPORTATION3_TOTAL", "12.00");
        formData.put("TRANSPORTATION4_DATE", "20121110");
        formData.put("TRANSPORTATION4_TYPE", "PARKING");
        formData.put("TRANSPORTATION4_TOTAL", "22.00");
        formData.put("TRANSPORTATION5_DATE", "20121110");
        formData.put("TRANSPORTATION5_TYPE", "TOLL");
        formData.put("TRANSPORTATION5_TOTAL", "1.65");
        formData.put("TRANSPORTATION6_DATE", "20121110");
        formData.put("TRANSPORTATION6_TYPE", "TOLL");
        formData.put("TRANSPORTATION6_TOTAL", "1.60");
        formData.put("NUM_OTHER_EXPENSES", "2");
        formData.put("OTHER1_DATE", "20121003");
        formData.put("OTHER1_JUSTIFICATION", "Conference Registration");
        formData.put("OTHER1_TOTAL", "450");
        formData.put("OTHER2_DATE", "20121003");
        formData.put("OTHER2_JUSTIFICATION", "Workshop Registration");
        formData.put("OTHER2_TOTAL", "100");
        formData.put("NUM_GRANTS", "1");
        formData.put("GRANT1_ACCOUNT", "010101010101");
        formData.put("GRANT1_PERCENT", "100");
        formData.put("GRANT1_AMOUNT_TO_CHARGE", "1086.24");
        formData.put("GRANT1_APPROVER_NAME", "heimd001");
        formData.put("TOTAL_REIMBURSEMENT", "1086.24");

        return formData;
    }

    // --------------------------------------------------------------------------
    // SET-UP AND TEAR-DOWN FOR ALL TESTS IN THIS SUITE (FILE).
    // --------------------------------------------------------------------------
    /**
     * Sets up the data needed for the tests in this suite.
     * 
     * @throws java.lang.Exception
     */
    @Before
    public void setUp() throws Exception {
        this.testProcessor = new TravelFormProcessor(this.userDB,
                this.perDiemDB, this.grantDB, this.userGrantDB, this.currencyDB);
        // this.testProcessor.setUser("linc001");
        // this.testProcessor.clearSavedForms();

        this.inputFormData = getDefaultForm();
        this.outputFormData = getOutputForm();
        this.description = "my form description";
    }

    /**
     * Tears down after the tests have completed.
     * 
     * @throws java.lang.Exception
     */
    @After
    public void tearDown() throws Exception {
        this.testProcessor = null;

        this.inputFormData = null;
        this.outputFormData = null;
        this.description = null;
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSetUserInDatabase() throws Exception {
        this.testProcessor.setUser("linc001");
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSetUserNotInDatabase() throws Exception {
        expectedException.expect(TrapException.class);
        expectedException.expectMessage("Invalid Key");
        this.testProcessor.setUser("linc002");

    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSetUserNull() throws Exception {
        expectedException.expect(NullPointerException.class);
        this.testProcessor.setUser(null);
    }

    /**
     * 
     */
    @Test
    public void testGetUserWithoutUserSet()
    {
        expectedException.expect(NullPointerException.class);
        this.testProcessor.getUser();
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testGetUserSetOnce() throws Exception {
        String currentUser = "";
        String expectedUser = "linc001";
        this.testProcessor.setUser(expectedUser);
        currentUser = this.testProcessor.getUser();
        assertEquals("Current user was " + currentUser + " instead of "
                + expectedUser, currentUser, expectedUser);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataInvalidFormId() throws Exception {
    	expectedException.expect(FormMemoryException.class);
        this.testProcessor.saveFormData(this.inputFormData, Integer.MAX_VALUE);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataInvalidFormId() throws Exception {
    	expectedException.expect(FormMemoryException.class);
        this.outputFormData = this.testProcessor.getSavedFormData(Integer.MAX_VALUE);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataNullDescription() throws Exception {
        String nullString = null;
        this.testProcessor.saveFormData(this.inputFormData, nullString);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataNullDescription() throws Exception {
    String nullString = null;
    int formId = this.testProcessor.saveFormData(this.inputFormData,
            nullString);
    this.outputFormData = this.testProcessor.getSavedFormData(formId);
    Set<String> keys = this.outputFormData.keySet();

    assertEquals("Output map size (" + this.outputFormData.size() + ") "
            + "didn't match input map size (" + this.inputFormData.size()
            + ")", this.outputFormData.size(), this.inputFormData.size());
    for (String key : keys)
        assertEquals("Output map didn't match input map for key " + key,
                this.outputFormData.get(key), this.inputFormData.get(key));
}
    
    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataNullMap() throws Exception {
        String description = "my description";
        this.testProcessor.saveFormData(null, description);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataNullMap() throws Exception {
        String description = "my description";
        int formId = this.testProcessor.saveFormData(null, description);
        this.outputFormData = this.testProcessor.getSavedFormData(formId);
        assertEquals("output form was not null", this.outputFormData, null);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataEmptyMap() throws Exception {
        String description = "my description";
        Map<String, String> map = getEmptyForm();
        this.testProcessor.saveFormData(map, description);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataEmptyMap() throws Exception {
        String description = "my description";
        Map<String, String> map = getEmptyForm();
        int formId = this.testProcessor.saveFormData(map, description);
        this.outputFormData = this.testProcessor.getSavedFormData(formId);

        Set<String> keys = this.outputFormData.keySet();

        assertEquals("Output map size (" + this.outputFormData.size() + ") "
                + "didn't match input map size (" + map.size() + ")",
                this.outputFormData.size(), map.size());
        for (String key : keys)
            assertEquals("Output map didn't match input map for key " + key,
                    this.outputFormData.get(key), map.get(key));
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataIncompleteMapInvalidData() throws Exception {
        String description = "my description";
        Map<String, String> map = getIncompleteForm();
        this.testProcessor.saveFormData(map, description);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataIncompleteMapInvalidData() throws Exception {
        String description = "my description";
        Map<String, String> map = getIncompleteForm();
        int formId = this.testProcessor.saveFormData(map, description);
        this.outputFormData = this.testProcessor.getSavedFormData(formId);

        Set<String> keys = this.outputFormData.keySet();

        assertEquals("Output map size (" + this.outputFormData.size() + ") "
                + "didn't match input map size (" + map.size() + ")",
                this.outputFormData.size(), map.size());
        for (String key : keys)
            assertEquals("Output map didn't match input map for key " + key,
                    this.outputFormData.get(key), map.get(key));
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataValidDataNew() throws Exception {
        String description = "my description";
        this.testProcessor.saveFormData(this.inputFormData, description);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataValidDataNew() throws Exception {
        String description = "my description";
        int formId = this.testProcessor.saveFormData(this.inputFormData,
                description);
        this.outputFormData = this.testProcessor.getSavedFormData(formId);

        Set<String> keys = this.outputFormData.keySet();

        assertEquals("Output map size (" + this.outputFormData.size() + ") "
                + "didn't match input map size (" + this.outputFormData.size()
                + ")", this.outputFormData.size(), this.outputFormData.size());
        for (String key : keys)
            assertEquals("Output map didn't match input map for key " + key,
                    this.outputFormData.get(key), this.outputFormData.get(key));
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataValidDataSameExisting() throws Exception {
        String description = "my description";
        Map<String, String> map = getDefaultForm();
        int formId = this.testProcessor.saveFormData(map, description);
        this.testProcessor.saveFormData(map, formId);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataValidDataSameExisting() throws Exception {
        String description = "my description";
        Map<String, String> map = getDefaultForm();
        int formId1 = this.testProcessor.saveFormData(map, description);
        int formId2 = this.testProcessor.saveFormData(map, formId1);
        this.outputFormData = this.testProcessor.getSavedFormData(formId2);

        Set<String> keys = this.outputFormData.keySet();

        assertEquals("Output map size (" + this.outputFormData.size() + ") "
                + "didn't match input map size (" + this.outputFormData.size()
                + ")", this.outputFormData.size(), this.outputFormData.size());
        for (String key : keys)
            assertEquals("Output map didn't match input map for key " + key,
                    this.outputFormData.get(key), this.outputFormData.get(key));
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testSaveFormDataValidDataDifferentExisting() throws Exception {
        String description = "my description";
        Map<String, String> map1 = getEmptyForm();
        Map<String, String> map2 = getDefaultForm();
        int formId = this.testProcessor.saveFormData(map1, description);
        this.testProcessor.saveFormData(map2, formId);
    }

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testLoadFormDataValidDataDifferentExisting() throws Exception {
        String description = "my description";
        Map<String, String> map1 = getEmptyForm();
        Map<String, String> map2 = getDefaultForm();
        int formId1 = this.testProcessor.saveFormData(map1, description);
        int formId2 = this.testProcessor.saveFormData(map2, formId1);
        this.outputFormData = this.testProcessor.getSavedFormData(formId2);

        Set<String> keys = this.outputFormData.keySet();

        assertEquals("Output map size (" + this.outputFormData.size() + ") "
                + "didn't match input map size (" + this.outputFormData.size()
                + ")", this.outputFormData.size(), this.outputFormData.size());
        for (String key : keys)
            assertEquals("Output map didn't match input map for key " + key,
                    this.outputFormData.get(key), this.outputFormData.get(key));
    }

   /**
    * 
    * @throws Exception
    */
   @Test
   public void testLoadListOfSavedFormsEmpty() throws Exception {
      
	   Map<Integer, TravelFormMetadata> savedForms = this.testProcessor.getSavedForms();
       assertEquals(0,savedForms.size());
   }

   /**
    * 
    * @throws Exception
    */
   @Test
   public void testLoadListOfSavedFormsMultiple() throws Exception {
       String description = "my description";
       Map<String, String> map1 = getEmptyForm();
       Map<String, String> map2 = getDefaultForm();
       this.testProcessor.saveFormData(map1, description + "1");
       this.testProcessor.saveFormData(map2, description + "2");

       Map<Integer, TravelFormMetadata> savedForms = this.testProcessor.getSavedForms();
       
       Set<String> keys;
       
       for(int i=0;i<savedForms.size();i++)
       {
            assertEquals(savedForms.get(i).description,description + Integer.toString(i+1));
            keys = savedForms.get(i).getFormMap().keySet();
            
            assertEquals(TravelFormProcessorIntf.FORM_STATUS.DRAFT,savedForms.get(i).status);
            
            assertEquals("Output map size (" + this.outputFormData.size() + ") "
                    + "didn't match input map size (" + this.outputFormData.size()
                    + ")", this.outputFormData.size(), this.outputFormData.size());
            for (String key : keys)
                assertEquals("Output map didn't match input map for key " + key,
                		savedForms.get(i).getFormMap().get(key), map2.get(key));
       }
   }

   /**
    * 
    * @throws Exception
    */
   @Test
   public void testClearListOfSavedFormsEmpty() throws Exception {
       Map<Integer, TravelFormMetadata> savedForms1 = this.testProcessor.getSavedForms();
       this.testProcessor.clearSavedForms();
       Map<Integer, TravelFormMetadata> savedForms2 = this.testProcessor.getSavedForms();
       assertEquals(0,savedForms1.size());
       assertEquals(0,savedForms2.size());
   }

   /**
    * 
    * @throws Exception
    */
   @Test
   public void testClearListOfSavedFormsMultiple() throws Exception {
       String description = "my description";
       Map<String, String> map1 = getEmptyForm();
       Map<String, String> map2 = getDefaultForm();
       this.testProcessor.saveFormData(map1, description + "1");
       this.testProcessor.saveFormData(map2, description + "2");

       assertEquals(true,this.testProcessor.getSavedForms().size() > 0);
       this.testProcessor.clearSavedForms();
       assertEquals(0,this.testProcessor.getSavedForms().size());
   }
   
   /**
    * Test method for {@link CheckLogicAirDomestic#update()}
    * 
    * This checks to make sure that a non-domestic air carrier is caught.
    */
   @Test
   public void testSubmitForm() throws Exception
   {
   	this.inputFormData  = getDefaultForm();
       
       //Save the form data, expecting no exception.
       Integer formId = this.testProcessor.saveFormData(this.inputFormData, this.description);
       
       Map<Integer, TravelFormMetadata> savedForms = this.testProcessor.getSavedForms();
       
       Set<Integer> keys = savedForms.keySet();
       
       
       //Otherwise, we have a valid form id.
   		this.testProcessor.submitFormData(formId);

    this.checkOutput(this.testProcessor.getCompletedForm(formId));
   }
   
   /**
    * Check the output to see if it matches what we expect.
    * @param actualOut  the form that was emitted by TRAP
    * @param earliestFormSubmissionTime  the earliest possible submission time
    *              to use in checking our times.
    * @throws ParseException
    */
   private void checkOutput(Map<String, String> actualOut) 
                   throws ParseException
   {
       assertNotNull(actualOut);
       
       //Check that they have the same size (assuming we are missing 1 field in
       //  our expected output, the form submission date)
       
       assertEquals(this.outputFormData.size() + 1, actualOut.size());
       
       //Now, check each key.
       for(String key : this.outputFormData.keySet())
       {
           String expectedValue = this.outputFormData.get(key);
           String actualValue   = actualOut.get(key);
           
           assertNotNull(actualValue);
        //   if(!key.contains("AMOUNT_TO_CHARGE") && !key.contains("TOTAL_REIMBURSEMENT"))
           	assertEquals("Should have been " + expectedValue + " but was " + actualValue + " for key " + key,
           		expectedValue, actualValue);
       }
       //We passed the output check.
   }
  

   
}
